import {defineStore} from 'pinia'
import * as R from 'ramda'
import { isAllZero } from '~/utils/funcs';

export type ProcessType = {
  pid: string;
  max: number[];
  need: number[];
  allocation: number[];
  status: boolean;
}

export const useStore = defineStore('data',  {
  state() {
    return {
      pid: '',
      resourceNum: 0,
      processNum: 0,
      avaliable: [] as number[],
      process: [] as ProcessType[]
    }
  }
})



export function getSafe(resourceNum: number, available: number[], processArr: ProcessType[]): {
  isSafe: boolean;
  safeQueue: number[];
  statusQueue: boolean[];
} {

		const processNum = processArr.length// parseInt(processNum.value.trim()),
		const need = processArr.reduce((pre, cur) => {
			return R.append(cur.need)(pre)
		}, [] as number[][])
		const allocation = processArr.reduce((pre, cur) => {
			return R.append(cur.allocation)(pre)
		}, [] as number[][])


  let safeIndex = 0;
  let allFinish = 0;
  let Finish = Array.from({length: processNum}, () => false);
  let safeSeries = Array.from({length: processNum}, () => 0);
  let r = 0;
  let temp = 0;
  let pNum = 0;

  //预分配为了保护available[]
  let work = [...available]
  const initAllZeroMap: Record<number, boolean> = {}

  //把未完成进程置为false
  for (let i = 0; i < processNum; i++) {
    let result = isAllZero(need[i]);
    if (result) {
      Finish[i] = true;
      initAllZeroMap[i] = true
      allFinish++;
    } else {
      Finish[i] = false;
    }
  }
  //预分配开始
  while (allFinish !== processNum) {
    let num = 0;
    // work 和 第r个进程的need比大小
    for (let i = 0; i < resourceNum; i++) {
      if (need[r][i] <= work[i] && !Finish[r]) {
        num++;
      }
    }
    // work >= need
    if (num == resourceNum || initAllZeroMap[r]) {
      if (initAllZeroMap[r]) {
        initAllZeroMap[r] = false
      } else {
        allFinish++;
      }
      // 释放资源
      for (let i = 0; i < resourceNum; i++) {
        work[i] = work[i] + allocation[r][i];
      }
      // 将被释放的进程的序号加入安全队列
      safeSeries[safeIndex] = r;
      safeIndex++;
      Finish[r] = true;
    }
    r++;//该式必须在此处
    if (r >= processNum) {
      r = r % processNum;
      if (temp == allFinish) {
        break;
      }
      temp = allFinish;
    }
    pNum = allFinish;
  }
  //判断系统是否安全
  for (let i = 0; i < processNum; i++) {
    if (!Finish[i]) {
      //console.log('mark: ', i)
      return {
        isSafe: false,
        safeQueue: [],
        statusQueue: Finish
      }
    }
  }
  // 获取安全序列
  for (let i = 0; i < processNum; i++) {
    let result = isAllZero(need[i]);
    if (result) {
      pNum--;
    }
  }
  let safeQueue:number[] = []
  for (let i = 0; i < processNum; i++) {
    safeQueue = [...safeQueue, safeSeries[i]]
  }
  return {
    isSafe: true,
    safeQueue: safeQueue,
    statusQueue: Finish
  }
}


export function getNeed(process: ProcessType) {
  let s = [] as number[]
  for (let j = 0; j < process.max.length; ++j) {
    const num = process.max[j] - process.allocation[j]
    s.push(num)
  }
  return s
}